#_*_ coding: UTF-8 _*_

import sys
from PyQt4 import QtCore, QtGui
import core.constants

rsrcPath = core.constants.app_path+"/images/win"

class TextEditorWindow(QtGui.QFrame):
	def __init__(self, parent=None):
		QtGui.QFrame.__init__(self, parent)

		self.ll = QVBoxLayout()

		self.setupFileActions()
		self.setupEditActions()
		self.setupTextActions()
		
		self.__optionToolBar = QtGui.QToolBar(self)
		self.__optionToolBar.setWindowTitle(u'اعمال کاربر')
		self.ll.addWidget(self.__optionToolBar)

		self.textEdit = QtGui.QTextEdit(self)
		QtCore.QObject.connect(self.textEdit, QtCore.SIGNAL('currentCharFormatChanged(QTextCharFormat)'), self.currentCharFormatChanged)
		self.ll.addWidget(self.textEdit)
		self.setLayout(self.ll)
		self.textEdit.setFocus()
		

		self.fontChanged(self.textEdit.font())
		self.colorChanged(self.textEdit.textColor())
		self.alignmentChanged(self.textEdit.alignment())

		QtCore.QObject.connect(self.textEdit.document(), QtCore.SIGNAL('modificationChanged(bool)'), self.actionSave.setEnabled)
		QtCore.QObject.connect(self.textEdit.document(), QtCore.SIGNAL('undoAvailable(bool)'), self.actionUndo.setEnabled)
		QtCore.QObject.connect(self.textEdit.document(), QtCore.SIGNAL('redoAvailable(bool)'), self.actionRedo.setEnabled)

		self.actionSave.setEnabled(self.textEdit.document().isModified())
		self.actionUndo.setEnabled(self.textEdit.document().isUndoAvailable())
		self.actionRedo.setEnabled(self.textEdit.document().isRedoAvailable())
		
		QtCore.QObject.connect(self.actionUndo, QtCore.SIGNAL('triggered()'), self.textEdit.document(), QtCore.SLOT('undo()'))
		QtCore.QObject.connect(self.actionRedo, QtCore.SIGNAL('triggered()'), self.textEdit.document(), QtCore.SLOT('redo()'))

		self.actionCut.setEnabled(False)
		self.actionCopy.setEnabled(False)
		
		QtCore.QObject.connect(self.actionCut, QtCore.SIGNAL('triggered()'), self.textEdit.cut)
		QtCore.QObject.connect(self.actionCopy, QtCore.SIGNAL('triggered()'), self.textEdit.copy)
		QtCore.QObject.connect(self.actionPaste, QtCore.SIGNAL('triggered()'), self.textEdit.paste)

		QtCore.QObject.connect(self.textEdit, QtCore.SIGNAL('copyAvailable(bool)'), self.actionCut.setEnabled)
		QtCore.QObject.connect(self.textEdit, QtCore.SIGNAL('copyAvailable(bool)'), self.actionCopy.setEnabled)

		QtCore.QObject.connect(QtGui.QApplication.clipboard(), QtCore.SIGNAL('dataChanged()'), self.clipboardDataChanged)

	def closeEvent(self, e):
		if self.mayBeSave():
			e.accept()
		else:
			e.ignore()

	def setupFileActions(self):
		tb = QtGui.QToolBar(self)
		tb.setWindowTitle(u'اعمال فایل')
		self.ll.addWidget(tb)

#		menu = QtGui.QMenu(u'فایل', self)
#		self.menuBar().addMenu(menu)

		a = QtGui.QAction(QtGui.QIcon(rsrcPath + '/fileprint.png'), u'چاپ', self)
		a.setShortcut('Ctrl+P')
		QtCore.QObject.connect(a, QtCore.SIGNAL('triggered()'), self.filePrint)
		tb.addAction(a)
#		menu.addAction(a)
		
		a = QtGui.QAction(QtGui.QIcon(rsrcPath + '/exportpdf.png'), u'ساخت PDF', self)
		a.setShortcut('Ctrl+D')
		QtCore.QObject.connect(a, QtCore.SIGNAL('triggered()'), self.filePrintPdf)
		tb.addAction(a)
#		menu.addAction(a)
		
		a = QtGui.QAction(QtGui.QIcon(rsrcPath + '/filesave.png'), u'ذخیره', self)
		self.actionSave = a
		a.setShortcut('Ctrl+S')
		QtCore.QObject.connect(a, QtCore.SIGNAL('triggered()'), self.__emitSave)
		a.setEnabled(False)
		tb.addAction(a)
#		menu.addAction(a)
		
	def setupEditActions(self):
		tb = QtGui.QToolBar(self)
		tb.setWindowTitle(u'اعمال ویرایش')
		self.ll.addWidget(tb)
			
#		menu = QtGui.QMenu(u'ویرایش', self)
#		self.menuBar().addMenu(menu)

		a = QtGui.QAction(QtGui.QIcon(rsrcPath + '/editundo.png'), u'بازگردانی عمل', self)
		self.actionUndo = a
		a.setShortcut('Ctrl+Z')
		tb.addAction(a)
#		menu.addAction(a)
		
		a = QtGui.QAction(QtGui.QIcon(rsrcPath + '/editredo.png'), u'عمل مجدد', self)
		self.actionRedo = a
		a.setShortcut('Ctrl+Y')
		tb.addAction(a)
#		menu.addAction(a)
		
#		menu.addSeparator()
		
		a = QtGui.QAction(QtGui.QIcon(rsrcPath + '/editcut.png'), u'برش', self)
		self.actionCut = a
		a.setShortcut('Ctrl+X')
		tb.addAction(a)
#		menu.addAction(a)
		
		a = QtGui.QAction(QtGui.QIcon(rsrcPath + '/editcopy.png'), u'کپی', self)
		self.actionCopy = a
		a.setShortcut('Ctrl+C')
		tb.addAction(a)
#		menu.addAction(a)
		
		a = QtGui.QAction(QtGui.QIcon(rsrcPath + '/editpaste.png'), u'چسباندن', self)
		self.actionPaste = a
		a.setShortcut('Ctrl+V')
		tb.addAction(a)
#		menu.addAction(a)
		
		self.actionPaste.setEnabled(not QtGui.QApplication.clipboard().text().isEmpty())
#		menu.addSeparator()

	def setupTextActions(self):
		tb = QtGui.QToolBar(self)
		tb.setWindowTitle(u'اعمال آرایش متن')
		self.ll.addwidget(tb)
		
#		menu = QtGui.QMenu(u'آرایش', self)
#		self.menuBar().addMenu(menu)

		self.actionTextBold = QtGui.QAction(QtGui.QIcon(rsrcPath + '/textbold.png'), u'سیاه', self)
		self.actionTextBold.setShortcut('Ctrl+B')
		bold = QtGui.QFont()
		bold.setBold(True)
		self.actionTextBold.setFont(bold)
		QtCore.QObject.connect(self.actionTextBold, QtCore.SIGNAL('triggered()'), self.textBold)
		tb.addAction(self.actionTextBold)
#		menu.addAction(self.actionTextBold)
		self.actionTextBold.setCheckable(True)
		
		self.actionTextItalic = QtGui.QAction(QtGui.QIcon(rsrcPath + '/textitalic.png'), u'کج', self)
		self.actionTextItalic.setShortcut('Ctrl+I')
		italic = QtGui.QFont()
		italic.setItalic(True)
		self.actionTextItalic.setFont(italic)
		QtCore.QObject.connect(self.actionTextItalic, QtCore.SIGNAL('triggered()'), self.textItalic)
		tb.addAction(self.actionTextItalic)
#		menu.addAction(self.actionTextItalic)
		self.actionTextItalic.setCheckable(True)
		
		self.actionTextUnderline = QtGui.QAction(QtGui.QIcon(rsrcPath + '/textunder.png'), u'زیر خط دار', self)
		self.actionTextUnderline.setShortcut('Ctrl+U')
		underline = QtGui.QFont()
		underline.setUnderline(True)
		self.actionTextUnderline.setFont(underline)
		QtCore.QObject.connect(self.actionTextUnderline, QtCore.SIGNAL('triggered()'), self.textUnderline)
		tb.addAction(self.actionTextUnderline)
#		menu.addAction(self.actionTextUnderline)
		self.actionTextUnderline.setCheckable(True)
		
#		menu.addSeparator()
		
#------------------ BECAUSE OF THE BUG OF ACTION GROUP TRIGGER ----------------
#		grp = QtGui.QActionGroup(self)
#		QtCore.QObject.connect(grp, QtCore.SIGNAL('triggered(QAction)'), self.textAlign)
#
#		self.actionAlignLeft = QtGui.QAction(QtGui.QIcon(rsrcPath + '/textleft.png'), u'چپ چین', grp)
#		self.actionAlignLeft.setShortcut('Ctrl+L')
#		self.actionAlignLeft.setCheckable(True)        
#
#		self.actionAlignRight = QtGui.QAction(QtGui.QIcon(rsrcPath + '/textright.png'), u'راست چین', grp)
#		self.actionAlignRight.setShortcut('Ctrl+R')
#		self.actionAlignRight.setCheckable(True)        
#
#		self.actionAlignCenter = QtGui.QAction(QtGui.QIcon(rsrcPath + '/textcenter.png'), u'وسط چین', grp)
#		self.actionAlignCenter.setShortcut('Ctrl+E')
#		self.actionAlignCenter.setCheckable(True)        
#
#		self.actionAlignJustify = QtGui.QAction(QtGui.QIcon(rsrcPath + '/textjustify.png'), u'تمام خط', grp)
#		self.actionAlignJustify.setShortcut('Ctrl+J')
#		self.actionAlignJustify.setCheckable(True)        
#
#		tb.addActions(grp.actions())
#		menu.addActions(grp.actions())

		self.actionAlignLeft = QtGui.QAction(QtGui.QIcon(rsrcPath + '/textleft.png'), u'چپ چین', self)
		self.actionAlignLeft.setShortcut('Ctrl+L')
		self.actionAlignLeft.setCheckable(True)        
		QtCore.QObject.connect(self.actionAlignLeft, QtCore.SIGNAL('triggered(bool)'), self.textAlignLeft)
		tb.addAction(self.actionAlignLeft)
#		menu.addAction(self.actionAlignLeft)

		self.actionAlignRight = QtGui.QAction(QtGui.QIcon(rsrcPath + '/textright.png'), u'راست چین', self)
		self.actionAlignRight.setShortcut('Ctrl+R')
		self.actionAlignRight.setCheckable(True)        
		QtCore.QObject.connect(self.actionAlignRight, QtCore.SIGNAL('triggered(bool)'), self.textAlignRight)
		tb.addAction(self.actionAlignRight)
#		menu.addAction(self.actionAlignRight)

		self.actionAlignCenter = QtGui.QAction(QtGui.QIcon(rsrcPath + '/textcenter.png'), u'وسط چین', self)
		self.actionAlignCenter.setShortcut('Ctrl+E')
		self.actionAlignCenter.setCheckable(True)        
		QtCore.QObject.connect(self.actionAlignCenter, QtCore.SIGNAL('triggered(bool)'), self.textAlignCenter)
		tb.addAction(self.actionAlignCenter)
#		menu.addAction(self.actionAlignCenter)

		self.actionAlignJustify = QtGui.QAction(QtGui.QIcon(rsrcPath + '/textjustify.png'), u'تمام خط', self)
		self.actionAlignJustify.setShortcut('Ctrl+J')
		self.actionAlignJustify.setCheckable(True)        
		QtCore.QObject.connect(self.actionAlignJustify, QtCore.SIGNAL('triggered(bool)'), self.textAlignJustify)
		tb.addAction(self.actionAlignJustify)
#		menu.addAction(self.actionAlignJustify)
#------------------ BECAUSE OF THE BUG OF ACTION GROUP TRIGGER ----------------
		
#		menu.addSeparator()
		
		pix = QtGui.QPixmap(16, 16)
		pix.fill(QtCore.Qt.black)
		self.actionTextColor = QtGui.QAction(QtGui.QIcon(pix), u'رنگ', self)
		QtCore.QObject.connect(self.actionTextColor, QtCore.SIGNAL('triggered()'), self.textColor)
		tb.addAction(self.actionTextColor)
#		menu.addAction(self.actionTextColor)

		tb = QtGui.QToolBar(self)
		tb.setAllowedAreas(QtCore.Qt.TopToolBarArea | QtCore.Qt.BottomToolBarArea)
		tb.setWindowTitle(u'اعمال آرایش متن')
#		self.addToolBarBreak(QtCore.Qt.TopToolBarArea)
		self.addWidget(tb)
		
		self.comboStyle = QtGui.QComboBox(tb)
		tb.addWidget(self.comboStyle)
		self.comboStyle.addItem(u'استاندارد')
		self.comboStyle.addItem(u'بولت (دایره توپر)')
		self.comboStyle.addItem(u'بولت (دایره توخالی)')
		self.comboStyle.addItem(u'بولت (مربع)')
		self.comboStyle.addItem(u'لیست (شماره)')
#		self.comboStyle.addItem(u'لیست (ابجد)')
		self.comboStyle.addItem(u'لیست (الفبا)')
		QtCore.QObject.connect(self.comboStyle, QtCore.SIGNAL('activated(int)'), self.textStyle)
		
		self.comboFont = QtGui.QComboBox(tb)
		tb.addWidget(self.comboFont)
		self.comboFont.setEditable(True)
		db = QtGui.QFontDatabase()
		self.comboFont.addItems(db.families())
		QtCore.QObject.connect(self.comboFont, QtCore.SIGNAL('activated(QString)'), self.textFamily)
		self.comboFont.setCurrentIndex(self.comboFont.findText(QtGui.QApplication.font().family()))

		self.comboSize = QtGui.QComboBox(tb)
		self.comboSize.setObjectName('comboSize')
		tb.addWidget(self.comboSize)
		self.comboSize.setEditable(True)
		
		for size in db.standardSizes():
			self.comboSize.addItem(QtCore.QString.number(size))
			
		QtCore.QObject.connect(self.comboSize, QtCore.SIGNAL('activated(QString)'), self.textSize)
		self.comboSize.setCurrentIndex(self.comboSize.findText(QtCore.QString.number(QtGui.QApplication.font().pointSize())))

	def mayBeSave(self):
		if not self.textEdit.document().isModified():
			return True
#		ret = QtGui.QMessageBox.warning(self, u'برنامه', u'متن تغییر کرده است. آیا می خواهید تغییرات ذخیره شود؟', QtGui.QMessageBox.Yes | QtGui.QMessageBox.Default, QtGui.QMessageBox.No, QtGui.QMessageBox.Cancel | QtGui.QMessageBox.Escape)
		ret = QtGui.QMessageBox.warning(self, u'برنامه', u'متن تغییر کرده است. آیا می خواهید تغییرات ذخیره شود؟', u'بله', u'لغو', u'خیر', 0, 1)
		
		if ret == 0:
			self.__emitSave()
			return True
		elif ret == 1:
			return False
		return True

	def filePrint(self):
		printer = QtGui.QPrinter(QtGui.QPrinter.HighResolution)
		printer.setFullPage(True)
		dlg = QtGui.QPrintDialog(printer, self)
		if dlg.exec_() == QtGui.QDialog.Accepted:
			self.textEdit.document().print_(printer)
	
	def filePrintPdf(self):
		fileName = QtGui.QFileDialog.getSaveFileName(self, u'ساخت PDF', QtCore.QString(''), '*.pdf')
		if fileName.isEmpty():
			return

		printer = QtGui.QPrinter(QtGui.QPrinter.HighResolution)
		printer.setOutputFormat(QtGui.QPrinter.PdfFormat)
		printer.setOutputFileName(fileName)
		self.textEdit.document().print_(printer)

	def textBold(self):
		if self.actionTextBold.isChecked():
			self.textEdit.setFontWeight(QtGui.QFont.Black)
		else:
			self.textEdit.setFontWeight(QtGui.QFont.Normal)

	def textUnderline(self):
		self.textEdit.setFontUnderline(self.actionTextUnderline.isChecked())

	def textItalic(self):
		self.textEdit.setFontItalic(self.actionTextItalic.isChecked())

	def textFamily(self, f):
		self.textEdit.setFontFamily(f)

	def textSize(self, p):
		vs = p.toFloat()
		if vs[1]:
			self.textEdit.setFontPointSize(vs[0])

	def textStyle(self, styleIndex):
		cursor = self.textEdit.textCursor()

		if styleIndex != 0:
			style = QtGui.QTextListFormat.ListDisc

			styleMap = { 1:QtGui.QTextListFormat.ListDisc, 2:QtGui.QTextListFormat.ListCircle, 3:QtGui.QTextListFormat.ListSquare, 4:QtGui.QTextListFormat.ListDecimal, 5:QtGui.QTextListFormat.ListLowerAlpha, 6:QtGui.QTextListFormat.ListUpperAlpha }
			if styleIndex<=5 and styleIndex>=1:
				style = styleMap[styleIndex]

			cursor.beginEditBlock()

			blockFmt = cursor.blockFormat()

			listFmt = QtGui.QTextListFormat()

			if cursor.currentList():
				listFmt = cursor.currentList().format()
			else:
				listFmt.setIndent(blockFmt.indent() +  1)
				blockFmt.setIndent(0)
				cursor.setBlockFormat(blockFmt)

			listFmt.setStyle(style)

			cursor.createList(listFmt)

			cursor.endEditBlock()
		
		else:
			bfmt = QtGui.QTextBlockFormat()
			bfmt.setObjectIndex(-1)
			cursor.mergeBlockFormat(bfmt)

	def textColor(self):
		col = QtGui.QColorDialog.getColor(self.textEdit.textColor(), self)
		if not col.isValid():
			return

		self.textEdit.setTextColor(col)
		self.colorChanged(col)

#------------------ BECAUSE OF THE BUG OF ACTION GROUP TRIGGER ----------------
#	def textAlign(self, a):
#		if a is self.actionAlignLeft:
#			self.textEdit.setAlignment(QtCore.Qt.AlignLeft)
#		elif a is self.actionAlignCenter:
#			self.textEdit.setAlignment(QtCore.Qt.AlignHCenter)
#		elif a is self.actionAlignRight:
#			self.textEdit.setAlignment(QtCore.Qt.AlignRight)
#		elif a is self.actionAlignJustify:
#			self.textEdit.setAlignment(QtCore.Qt.AlignJustify)

	def textAlignLeft(self, dummy):
			self.textEdit.setAlignment(QtCore.Qt.AlignLeft)
			self.alignmentChanged(QtCore.Qt.AlignLeft)
			
	def textAlignCenter(self, dummy):
			self.textEdit.setAlignment(QtCore.Qt.AlignHCenter)
			self.alignmentChanged(QtCore.Qt.AlignHCenter)

	def textAlignRight(self, dummy):
			self.textEdit.setAlignment(QtCore.Qt.AlignRight)
			self.alignmentChanged(QtCore.Qt.AlignRight)

	def textAlignJustify(self, dummy):
			self.textEdit.setAlignment(QtCore.Qt.AlignJustify)
			self.alignmentChanged(QtCore.Qt.AlignJustify)
#------------------ END: BECAUSE OF THE BUG OF ACTION GROUP TRIGGER ----------------

	def currentCharFormatChanged(self, format):
		self.fontChanged(format.font())
		self.colorChanged(format.foreground().color())
		self.alignmentChanged(self.textEdit.alignment())

	def clipboardDataChanged(self):
		self.actionPaste.setEnabled(not QtGui.QApplication.clipboard().text().isEmpty())

	def fontChanged(self, f):
		self.comboFont.setCurrentIndex(self.comboFont.findText(f.family()))
		self.comboSize.setCurrentIndex(self.comboSize.findText(QtCore.QString.number(f.pointSize())))
		self.actionTextBold.setChecked(f.bold())
		self.actionTextItalic.setChecked(f.italic())
		self.actionTextUnderline.setChecked(f.underline())

	def colorChanged(self, c):
		pix = QtGui.QPixmap(16, 16)
		pix.fill(c)
		self.actionTextColor.setIcon(QtGui.QIcon(pix))

	def alignmentChanged(self, a):
#------------------ BECAUSE OF THE BUG OF ACTION GROUP TRIGGER ----------------
		self.actionAlignLeft.setChecked(False)
		self.actionAlignRight.setChecked(False)
		self.actionAlignCenter.setChecked(False)
		self.actionAlignJustify.setChecked(False)
#------------------ END: BECAUSE OF THE BUG OF ACTION GROUP TRIGGER ----------------

		if (a & QtCore.Qt.AlignLeft):
			self.actionAlignLeft.setChecked(True)
		elif (a & QtCore.Qt.AlignHCenter):
			self.actionAlignCenter.setChecked(True)
		elif (a & QtCore.Qt.AlignRight):
			self.actionAlignRight.setChecked(True)
		elif (a & QtCore.Qt.AlignJustify):
			self.actionAlignJustify.setChecked(True)
			
	def __emitSave(self):
		self.textEdit.document().setModified(False)
		self.emit(QtCore.SIGNAL('saveRequest()'))
		
	def optionToolBar(self):
		return self.__optionToolBar
	
	def contentToHtml(self):
		return self.textEdit.toHtml()
	
	def contentToPlainText(self):
		return self.textEdit.toPlainText()()
	
	def setContent(self, str):
		if QtCore.Qt.mightBeRichText(str):
			self.textEdit.setHtml(str)
		else:
			self.textEdit.setPlainText(str)

	def loadFile(self, f):
		if not QtCore.QFile.exists(f):
			return False
		file = QtCore.QFile(f)
		if not file.open(QtCore.QFile.ReadOnly):
			return False
		
		data = file.readAll()
		codec = QtCore.QTextCodec.codecForHtml(data)
		str = codec.toUnicode(data)
		if QtCore.Qt.mightBeRichText(str):
			self.textEdit.setHtml(str)
		else:
#			str = QtCore.QString.fromLocal8Bit(data.__str__())
			self.textEdit.setPlainText(str)
			
		return True
	
if __name__ == '__main__':
	def say1():
		print 'user request: delete'
	def say2():
		print 'editor request: save'
	
	app = QtGui.QApplication(sys.argv)
	app.setLayoutDirection(QtCore.Qt.RightToLeft)
	
	mainWindow = TextEditorWindow()
	mainWindow.setWindowState(QtCore.Qt.WindowMaximized)
	mainWindow.show()
	
	tb = mainWindow.optionToolBar()
	a = QtGui.QAction(QtGui.QIcon(rsrcPath + '/delete.png'), u'حذف', mainWindow)
	QtCore.QObject.connect(a, QtCore.SIGNAL('triggered()'), say1)
	tb.addAction(a)

	QtCore.QObject.connect(mainWindow, QtCore.SIGNAL('saveRequest()'), say2)
	
	mainWindow.loadFile(r'example.html')

	sys.exit(app.exec_())
		
